package com.cn.main.framework;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.cglib.proxy.Proxy;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.objenesis.instantiator.util.ClassUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * user : chenyuncong
 * create_time : 2022/8/22
 */
public class ProxyFactoryBean <T> implements FactoryBean {
    private static final Map<Class<? extends ProxyHandler>,ProxyHandler> ProxyHandlers = new ConcurrentHashMap<>();

    private Class<T> interfaceClass;
    private Class<? extends ProxyHandler> proxyHandlerType;

    public ProxyFactoryBean(Class<T> interfaceClass) {
        this.interfaceClass = interfaceClass;
        this.proxyHandlerType = AnnotationUtils.findAnnotation(interfaceClass, ProxyBean.class).value();
        if(!ProxyFactoryBean.ProxyHandlers.containsKey(proxyHandlerType)) {
            ProxyHandler proxyHandler = ClassUtils.newInstance(proxyHandlerType);
            SpringBean.inject(proxyHandler);
            ProxyFactoryBean.ProxyHandlers.put(proxyHandlerType, proxyHandler);
        }
    }

    @Override
    public T getObject() throws Exception {
        final ProxyHandler proxyHandler = ProxyFactoryBean.ProxyHandlers.get(proxyHandlerType);
        return (T) Proxy.newProxyInstance(
                interfaceClass.getClassLoader(),
                new Class[]{interfaceClass},
                (proxy,method,args) ->   proxyHandler.execute(interfaceClass,method,args)
        );
    }

    @Override
    public Class<T> getObjectType() {
        return interfaceClass;
    }
}
